{
  "bundles": [
    {
      "@type": "NXBundle",
      "artifactId": "nuxeo-core-binarymanager-s3",
      "artifactVersion": "2025.27.34",
      "bundleGroup": {
        "@type": "NXBundleGroup",
        "bundleIds": [
          "org.nuxeo.ecm.core.storage.binarymanager.common",
          "org.nuxeo.ecm.core.storage.binarymanager.s3"
        ],
        "hierarchyPath": "/grp:org.nuxeo.ecm.core/grp:org.nuxeo.ecm.core.storage/grp:org.nuxeo.ecm.core.storage.binarymanager",
        "id": "grp:org.nuxeo.ecm.core.storage.binarymanager",
        "name": "org.nuxeo.ecm.core.storage.binarymanager",
        "parentIds": [
          "grp:org.nuxeo.ecm.core.storage",
          "grp:org.nuxeo.ecm.core"
        ],
        "readmes": [],
        "version": "2025.27"
      },
      "bundleId": "org.nuxeo.ecm.core.storage.binarymanager.s3",
      "components": [
        {
          "@type": "NXComponent",
          "documentationHtml": "",
          "extensionPoints": [],
          "extensions": [],
          "hierarchyPath": "/grp:org.nuxeo.ecm.core/grp:org.nuxeo.ecm.core.storage/grp:org.nuxeo.ecm.core.storage.binarymanager/org.nuxeo.ecm.core.storage.binarymanager.s3/org.nuxeo.ecm.core.storage.cloud.requestcontroller.service.contrib",
          "name": "org.nuxeo.ecm.core.storage.cloud.requestcontroller.service.contrib",
          "requirements": [],
          "resolutionOrder": 110,
          "services": [],
          "startOrder": 160,
          "version": "2025.27.34",
          "xmlFileContent": "<?xml version=\"1.0\"?>\n<component name=\"org.nuxeo.ecm.core.storage.cloud.requestcontroller.service.contrib\">\n    <!-- Deprecated since 2025.13, the contribution moved to the amazon-s3-online-storage package. -->\n</component>\n",
          "xmlFileName": "/OSGI-INF/s3web-request-controller-contrib.xml",
          "xmlPureComponent": true
        },
        {
          "@type": "NXComponent",
          "documentationHtml": "",
          "extensionPoints": [],
          "extensions": [],
          "hierarchyPath": "/grp:org.nuxeo.ecm.core/grp:org.nuxeo.ecm.core.storage/grp:org.nuxeo.ecm.core.storage.binarymanager/org.nuxeo.ecm.core.storage.binarymanager.s3/org.nuxeo.ecm.core.storage.s3.config",
          "name": "org.nuxeo.ecm.core.storage.s3.config",
          "requirements": [],
          "resolutionOrder": 111,
          "services": [],
          "startOrder": 166,
          "version": "2025.27.34",
          "xmlFileContent": "<?xml version=\"1.0\"?>\n<component name=\"org.nuxeo.ecm.core.storage.s3.config\" version=\"1.0\">\n\n  <!--\n    The nuxeo.s3.multipart.copy.part.size ConfigurationService property is deprecated since 2021.11,\n    use the nuxeo.s3storage.multipart.copy.part.size nuxeo.conf property instead.\n  -->\n\n</component>\n",
          "xmlFileName": "/OSGI-INF/configuration-properties.xml",
          "xmlPureComponent": true
        },
        {
          "@type": "NXComponent",
          "documentationHtml": "",
          "extensionPoints": [],
          "extensions": [
            {
              "@type": "NXContribution",
              "documentationHtml": "",
              "extensionPoint": "org.nuxeo.ecm.core.scroll.service--scroll",
              "hierarchyPath": "/grp:org.nuxeo.ecm.core/grp:org.nuxeo.ecm.core.storage/grp:org.nuxeo.ecm.core.storage.binarymanager/org.nuxeo.ecm.core.storage.binarymanager.s3/org.nuxeo.ecm.core.storage.s3.bulk.config/Contributions/org.nuxeo.ecm.core.storage.s3.bulk.config--scroll",
              "id": "org.nuxeo.ecm.core.storage.s3.bulk.config--scroll",
              "registrationOrder": 8,
              "targetComponentName": {
                "rawName": "service:org.nuxeo.ecm.core.scroll.service",
                "name": "org.nuxeo.ecm.core.scroll.service",
                "type": "service"
              },
              "version": "2025.27.34",
              "xml": "<extension point=\"scroll\" target=\"org.nuxeo.ecm.core.scroll.service\">\n    <scroll class=\"org.nuxeo.ecm.blob.s3.S3BlobScroll\" name=\"s3BlobScroll\" type=\"generic\"/>\n  </extension>"
            },
            {
              "@type": "NXContribution",
              "documentationHtml": "",
              "extensionPoint": "org.nuxeo.ecm.core.bulk--actions",
              "hierarchyPath": "/grp:org.nuxeo.ecm.core/grp:org.nuxeo.ecm.core.storage/grp:org.nuxeo.ecm.core.storage.binarymanager/org.nuxeo.ecm.core.storage.binarymanager.s3/org.nuxeo.ecm.core.storage.s3.bulk.config/Contributions/org.nuxeo.ecm.core.storage.s3.bulk.config--actions",
              "id": "org.nuxeo.ecm.core.storage.s3.bulk.config--actions",
              "registrationOrder": 19,
              "targetComponentName": {
                "rawName": "service:org.nuxeo.ecm.core.bulk",
                "name": "org.nuxeo.ecm.core.bulk",
                "type": "service"
              },
              "version": "2025.27.34",
              "xml": "<extension point=\"actions\" target=\"org.nuxeo.ecm.core.bulk\">\n    <action batchSize=\"25\" bucketSize=\"100\" enabled=\"false\" httpEnabled=\"true\" inputStream=\"bulk/s3SetBlobLength\" name=\"s3SetBlobLength\"/>\n  </extension>"
            },
            {
              "@type": "NXContribution",
              "documentationHtml": "",
              "extensionPoint": "org.nuxeo.runtime.stream.service--streamProcessor",
              "hierarchyPath": "/grp:org.nuxeo.ecm.core/grp:org.nuxeo.ecm.core.storage/grp:org.nuxeo.ecm.core.storage.binarymanager/org.nuxeo.ecm.core.storage.binarymanager.s3/org.nuxeo.ecm.core.storage.s3.bulk.config/Contributions/org.nuxeo.ecm.core.storage.s3.bulk.config--streamProcessor",
              "id": "org.nuxeo.ecm.core.storage.s3.bulk.config--streamProcessor",
              "registrationOrder": 23,
              "targetComponentName": {
                "rawName": "service:org.nuxeo.runtime.stream.service",
                "name": "org.nuxeo.runtime.stream.service",
                "type": "service"
              },
              "version": "2025.27.34",
              "xml": "<extension point=\"streamProcessor\" target=\"org.nuxeo.runtime.stream.service\">\n    <streamProcessor class=\"org.nuxeo.ecm.core.bulk.S3SetBlobLengthAction\" defaultConcurrency=\"2\" defaultPartitions=\"4\" enabled=\"false\" name=\"s3SetBlobLength\">\n      <policy continueOnFailure=\"true\" delay=\"500ms\" maxDelay=\"10s\" maxRetries=\"3\" name=\"default\"/>\n    </streamProcessor>\n\n  </extension>"
            }
          ],
          "hierarchyPath": "/grp:org.nuxeo.ecm.core/grp:org.nuxeo.ecm.core.storage/grp:org.nuxeo.ecm.core.storage.binarymanager/org.nuxeo.ecm.core.storage.binarymanager.s3/org.nuxeo.ecm.core.storage.s3.bulk.config",
          "name": "org.nuxeo.ecm.core.storage.s3.bulk.config",
          "requirements": [
            "org.nuxeo.runtime.stream.service",
            "org.nuxeo.ecm.core.scroll.service"
          ],
          "resolutionOrder": 630,
          "services": [],
          "startOrder": 165,
          "version": "2025.27.34",
          "xmlFileContent": "<?xml version=\"1.0\"?>\n<component name=\"org.nuxeo.ecm.core.storage.s3.bulk.config\" version=\"1.0.0\">\n\n  <require>org.nuxeo.runtime.stream.service</require>\n  <require>org.nuxeo.ecm.core.scroll.service</require>\n\n  <extension point=\"scroll\" target=\"org.nuxeo.ecm.core.scroll.service\">\n    <scroll type=\"generic\" name=\"s3BlobScroll\" class=\"org.nuxeo.ecm.blob.s3.S3BlobScroll\" />\n  </extension>\n\n  <extension target=\"org.nuxeo.ecm.core.bulk\" point=\"actions\">\n    <action name=\"s3SetBlobLength\" inputStream=\"bulk/s3SetBlobLength\" bucketSize=\"100\" batchSize=\"25\" httpEnabled=\"true\"\n      enabled=\"${binarymanager.bulk.s3SetBlobLength.enabled:=false}\" />\n  </extension>\n\n  <extension target=\"org.nuxeo.runtime.stream.service\" point=\"streamProcessor\">\n    <streamProcessor name=\"s3SetBlobLength\" class=\"org.nuxeo.ecm.core.bulk.S3SetBlobLengthAction\"\n      defaultConcurrency=\"${binarymanager.bulk.s3SetBlobLength.concurrency:=2}\"\n      defaultPartitions=\"${binarymanager.bulk.s3SetBlobLength.partitions:=4}\"\n      enabled=\"${binarymanager.bulk.s3SetBlobLength.enabled:=false}\">\n      <policy name=\"default\" maxRetries=\"3\" delay=\"500ms\" maxDelay=\"10s\" continueOnFailure=\"true\" />\n    </streamProcessor>\n\n  </extension>\n\n</component>\n",
          "xmlFileName": "/OSGI-INF/bulk-config.xml",
          "xmlPureComponent": true
        }
      ],
      "fileName": "nuxeo-core-binarymanager-s3-2025.27.34.jar",
      "groupId": "org.nuxeo.ecm.core",
      "hierarchyPath": "/grp:org.nuxeo.ecm.core/grp:org.nuxeo.ecm.core.storage/grp:org.nuxeo.ecm.core.storage.binarymanager/org.nuxeo.ecm.core.storage.binarymanager.s3",
      "id": "org.nuxeo.ecm.core.storage.binarymanager.s3",
      "location": "",
      "manifest": "Manifest-Version: 1.0\r\nCreated-By: Maven JAR Plugin 3.5.1\r\nJava-Version: 21\r\nBuild-Jdk-Spec: 21\r\nBundle-ManifestVersion: 2\r\nBundle-SymbolicName: org.nuxeo.ecm.core.storage.binarymanager.s3;singlet\r\n on:=true\r\nNuxeo-Component: OSGI-INF/s3web-request-controller-contrib.xml,OSGI-INF/\r\n configuration-properties.xml,OSGI-INF/bulk-config.xml\r\n\r\n",
      "maxResolutionOrder": 630,
      "minResolutionOrder": 110,
      "packages": [
        "amazon-s3-online-storage"
      ],
      "readme": {
        "blobProviderId": "default",
        "content": "# nuxeo-core-binarymanager-s3\n\nThis addon implements a BinaryManager that stores binaries in a S3 bucket.\nFor efficiency, a local disk cache (with limited size) is also used.\n\nBe sure to protect your nuxeo.conf (readable only by the nuxeo user) as the\nfile will have your AWS identifiers (unless you are using instance roles).\n\n## Mandatory Parameters\n\n- nuxeo.core.binarymanager=org.nuxeo.ecm.blob.s3.S3BlobProvider\n\n- nuxeo.s3storage.bucket : the name of the S3 bucket (unique across all of\n  Amazon, find something original!)\n\n- nuxeo.s3storage.awsid : your AWS_ACCESS_KEY_ID\n\n- nuxeo.s3storage.awssecret : your AWS_SECRET_ACCESS_KEY\n\nIf the awsid and/or awssecret are not set, the addon will try to use\ntemporary credentials from the instance role (if any).\n\n## Optional Parameters\n\n- nuxeo.s3storage.region : the region code your S3 bucket will be placed in.\n  For us-east-1 (the default), don't set this parameter\n  For us-west-1 (Northern California), use us-west-1\n  For us-west-2 (Oregon), use us-west-2\n  For eu-west-1 (Ireland), use EU\n  For ap-southeast-1 (Singapore), use ap-southeast-1\n  For ap-northeast-1 (Tokyo), use ap-northeast-1\n  For sa-east-1 (Sao Paulo), use sa-east-1\n\n- nuxeo.s3storage.cachesize : size of the local cache (default is 100MiB).\n- nuxeo.s3storage.bucket_prefix : bucket prefix\n- nuxeo.s3storage.pathstyleaccess : if `true`, configures the client to use path-style access for all requests (default is `false`)\n\n## Crypto Parameters\n\nWith S3, you have the option to store your data encrypted.\nNote that the local cache will *NOT* be encrypted.\n\nThe S3 binary manager can use a keystore containing a keypair, but there are\na few caveats to be aware of :\n\n- The Sun/Oracle JDK doesn't always allow the AES256 cipher which the AWS SDK\n  uses internally.\n  Depending on the US export restrictions for your country, you may be able to\n  modify your JDK to use AES256 by installing the \"Java Cryptography Extension\n  Unlimited Strength Jurisdiction Policy Files\". See this [link](http://www.oracle.com/technetwork/java/javase/downloads/index.html) to\n  download the files and installation instructions.\n\n- Don't forget to specify the key algorithm if you create your keypair with the\n  \"keytool\" command, as this won't work with the default (DSA).\n  The S3 Binary Manager has been tested with a keystore generated with this\n  command :\n\n  ```shell\n  keytool -genkeypair -keystore </path/to/keystore/file> -alias <key alias>\n      -storepass <keystore password> -keypass <key password>\n      -dname <key distinguished name> -keyalg RSA\n  ```\n\nWith all that preceded in mind, here are the crypto options (they are all\nmandatory once you specify a keystore) :\n\n- nuxeo.s3storage.crypt.keystore.file : the absolute path to the keystore file\n- nuxeo.s3storage.crypt.keystore.password : the keystore password\n- nuxeo.s3storage.crypt.key.alias = the key alias\n- nuxeo.s3storage.crypt.key.password = the key password\n\n### Client-side Encryption Object Format\n\nClient-side encryption relies on the [Amazon S3 Encryption Client](https://github.com/aws/amazon-s3-encryption-client-java),\nwhich offers a few storage choices. Nuxeo uses the following ones:\n\n- The encrypted data key is always stored in the **S3 object metadata**. Instruction files (a sibling\n  `<key>.instruction` object holding the encryption metadata) are neither written nor read.\n\n  Reading an object which holds no encryption metadata therefore fails, where it used to be reported as a missing\n  blob. Objects written by another client with the instruction file storage mode, which Nuxeo never used, cannot be\n  read.\n\n- Objects are written **without key commitment** (commitment policy `FORBID_ENCRYPT_ALLOW_DECRYPT`), so that a blob\n  written by Nuxeo stays readable by any 3.x or 4.x version of the encryption client. Objects encrypted with key\n  commitment are still readable.\n\n## Server-side Encryption\n\nS3 allows you to use server-side encryption to encrypt data at rest with keys managed\nby S3 itself. To activate-this mode, use:\n\n- nuxeo.s3storage.crypt.serverside = true\n\nSee the related AWS [documentation](http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html) for more.\n\nIf you want to use Server-Side Encryption with AWS KMS–Managed Keys, specify your key id with:\n\n- nuxeo.s3storage.crypt.kms.key = your-key-id\n\nSee the related AWS [documentation](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html) for more.\n\n## Enable CloudFront Direct Download\n\nPlease, read carefully the [CloudFront documentation](https://aws.amazon.com/fr/documentation/cloudfront/) to understand how you bind a CloudFront distribution to a S3 bucket.\nAfter you created a CloudFront distribution domain bound to your S3 repository. Accessing your objects is not restricted per default.\n\nYou have to enable the `restriction viewer access` (Look at [Serving Private Content throught CloudFront](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html)), then each distribution URL must be signed to access the target object.\n\nYou have to set the `Query String Forwarding and Caching` on `all parameters` (Look at [Configuring CloudFront to Cache Based on Query String Parameters](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html)) in order to correctly forward `Content Disposition` parameters to get a response with a correct filename.\n\n### CloudFront Mandatory Parameters\n\nS3 parameters (except `nuxeo.core.binarymanager`) are mandatory, additionally CloudFront requires some new ones:\n\n- `nuxeo.core.binarymanager=org.nuxeo.ecm.core.storage.sql.CloudFrontBinaryManager`\n- `nuxeo.s3storage.cloudfront.privKey`: the absolute path of the private key file (`.pem` or `.der`). Read: [Creating CloudFront Key Pairs for Your Trusted Signers](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html#private-content-creating-cloudfront-key-pairs)\n- `nuxeo.s3storage.cloudfront.privKeyId`: the private key id.\n- `nuxeo.s3storage.cloudfront.distribDomain`: the distribution domain name.\n- `nuxeo.s3storage.cloudfront.protocol`: the prefered protocol (default `HTTPS`)\n- `nuxeo.s3storage.cloudfront.fix.encoding`: Enable a workaround to fix an error on CloudFront side (default `false`)\n\n## Digest Configuration\n\n- `nuxeo.s3storage.digest` : the digest algorithm used for blob keys (default `MD5`). Supported values include `MD5`, `SHA-1`, `SHA-256`.\n\n- `nuxeo.s3storage.digestAsync` : if `true`, digest computation is done asynchronously after the blob is stored (default `false`). Required when blobs are uploaded directly to S3 (direct upload) and digest needs to be computed server-side.\n\n- `nuxeo.s3storage.digest.maxSize` : maximum blob size for digest-based keys. Blobs larger than this threshold are stored with a UUIDv7 key instead of computing a content digest. Accepts byte size values like `5g`, `500m`, `1024k`. Default is disabled (all blobs get a digest key).\n\n  When enabled:\n  - Blobs at or below the threshold get a content-based digest key (e.g., MD5) with deduplication.\n  - Blobs above the threshold get a unique UUIDv7 key — no digest computation, no deduplication.\n  - Both key formats coexist transparently. Existing digest-keyed blobs remain valid.\n  - This is useful for very large files (50 GB+) where digest computation can exceed Kafka `max.poll.interval.ms`.\n  - Note: with SSE-KMS encryption, S3 ETags are opaque and cannot be used as digests, making this threshold approach the recommended solution for large files.\n\n## Synchronous I/O Configuration\n\nBy default, the addon uses the AWS CRT-based S3 transfer manager for both downloads and uploads. The transfer manager exposes an **asynchronous** API on top of `S3AsyncClient` and internally issues parallel range GETs and parallel multipart uploads, yielding significant throughput gains on AWS S3. This is the recommended setting for AWS S3 deployments.\n\nAgainst some S3-compatible gateways, the CRT-based async client has been observed to hang — on downloads with some gateways, on uploads with others. (The AWS SDK's other async transport, the Netty-based client, has shown similar issues, notably on uploads; this addon does not use it.) When the CRT client misbehaves, you can force one or both directions of I/O onto the **synchronous** Apache HTTP client (`S3Client` with `ApacheHttpClient`), which issues one blocking request per operation and bypasses the async transports entirely. The two properties below are independent — enable each one only when needed.\n\n- `nuxeo.s3storage.syncDownload` : if `true`, downloads use the synchronous Apache HTTP client instead of the CRT-based transfer manager (default `false`).\n\n- `nuxeo.s3storage.syncUpload` : if `true`, uploads use the synchronous Apache HTTP client instead of the CRT-based transfer manager (default `false`). The synchronous client uses a single `PutObject` request and is therefore limited to objects of 5 GiB or less; larger blobs are rejected up-front with a `NuxeoException` before any S3 traffic.\n\n## Building\n\n```shell\nmvn clean install\n```\n\n## Testing\n\nRunning the unit tests requires some environment variables and System properties to be set, otherwise they are skipped.\n\n### Environment Variables\n\n```shell\n  AWS_REGION=eu-west-3\n  AWS_ACCESS_KEY_ID=******\n  AWS_SECRET_ACCESS_KEY=******\n  AWS_ROLE_ARN=arn:aws:iam::783725821734:role/nuxeo-s3directupload-role\n```\n\n### System Properties\n\n```shell\nmvn test \\\n  -nsu \\\n  -Dnuxeo.test.s3storage.bucket=nuxeo-platform-unit-tests \\\n  -Dnuxeo.test.s3storage.transient.bucket=nuxeo-platform-unit-tests-transient \\\n  -Dnuxeo.test.s3storage.bucket_prefix=BUCKET_PREFIX \\\n  -Dnuxeo.test.s3storage.provider.test.bucket_prefix=TEST_BLOB_PROVIDER_PREFIX \\\n  -Dnuxeo.test.s3storage.provider.other.bucket_prefix=OTHER_BLOB_PROVIDER_PREFIX\n```\n\n## Deploying\n\nInstall [the Amazon S3 Online Storage Marketplace Package](https://connect.nuxeo.com/nuxeo/site/marketplace/package/amazon-s3-online-storage).\nOr manually copy the built artifacts into `$NUXEO_HOME/templates/custom/bundles/` and activate the \"custom\" template.\n\n## About Nuxeo\n\nNuxeo dramatically improves how content-based applications are built, managed and deployed, making customers more agile, innovative and successful. Nuxeo provides a next generation, enterprise ready platform for building traditional and cutting-edge content oriented applications. Combining a powerful application development environment with SaaS-based tools and a modular architecture, the Nuxeo Platform and Products provide clear business value to some of the most recognizable brands including Verizon, Electronic Arts, Sharp, FICO, the U.S. Navy, and Boeing. Nuxeo is headquartered in New York and Paris. More information is available at www.nuxeo.com.\n",
        "digest": "66e541d3ff0cab8524b7f194fc0a1324",
        "encoding": "UTF-8",
        "length": 10834,
        "mimeType": "text/plain",
        "name": "README.md"
      },
      "requirements": [],
      "version": "2025.27.34"
    }
  ],
  "creationDate": 1793873591050,
  "key": "Nuxeo Platform-2025.27",
  "name": "Nuxeo Platform",
  "operations": [],
  "packages": [
    {
      "@type": "NXPackage",
      "bundles": [
        "org.nuxeo.ecm.core.storage.binarymanager.common",
        "org.nuxeo.ecm.core.storage.binarymanager.s3",
        "org.nuxeo.runtime.aws"
      ],
      "conflicts": [],
      "dependencies": [],
      "hierarchyPath": "/amazon-s3-online-storage-2025.27.34",
      "id": "amazon-s3-online-storage-2025.27.34",
      "name": "amazon-s3-online-storage",
      "optionalDependencies": [],
      "packageType": "addon",
      "title": "Amazon S3 Online Storage",
      "version": "2025.27.34"
    }
  ],
  "pluginSnapshots": {},
  "releaseDate": 1793873591050,
  "version": "2025.27"
}